package com.bstu.ciit.lab3;
import java.util.Random;


public class Dog {
	private int count; // The number of chromosomes in the population
	private int size; // The size of the chromosomes
	private int chromosoms[][];
	private int fitnes[];
	private double mutation=0.1;
	private int max=100000;
	public int[][] getChromosoms() {
		return chromosoms;
	}
	public boolean badPopulation()
	{
		for (int i=0;i<count;i++)
			if (fitnes[i]!=max)
				return false;
		return true;
	}
	public void setChromosoms(int[][] chromosoms) {
		this.chromosoms = chromosoms;
	}
	public int getCount() {
		return count;
	}
	public int getSize() {
		return size;
	}
	public Dog(int count, int size)
	{
		Random random = new Random();
		this.count=count;
		this.size=size;
		this.chromosoms=new int[this.count][this.size];
		//Random filling
		for (int i=0; i<count; i++)
			for (int j=0; j<size; j++)
					this.chromosoms[i][j]=random.nextInt(4);	
		this.fitnes=new int[count];
	}
	public void print()
	{
		for(int i=0;i<count;i++)
		{
			for(int j=0;j<size;j++)
			{
				System.out.print(this.chromosoms[i][j]+" ");
			}
			System.out.println();
		}
	}
	public void fitnesCalculate(Field field)
	{
		int koord[]=new int[2];
		int home[]=field.getHome();
		for(int i=0;i<count;i++)
		{
			koord[0]=home[0];
			koord[1]=home[1];
			for(int j=0;j<size;j++)
			{
				if (chromosoms[i][j]==0)
					koord[1]-=1;
				else if (chromosoms[i][j]==1)
					koord[0]+=1;
				else if (chromosoms[i][j]==2)
					koord[1]+=1;
				else koord[0]-=1;
				int[] food=field.getFood();
				if (koord[0]<0)
					koord[0]+=field.getLength();
				if (koord[1]<0)
					koord[1]+=field.getWidth();
				if (koord[0]>=field.getLength())
					koord[0]-=field.getLength();
				if (koord[1]>=field.getWidth())
					koord[1]-=field.getWidth();
				if (koord[0]==food[0] && koord[1]==food[1])
				{
					fitnes[i]=-1;
					break;
				}
				if (field.ofWall(koord))
					break;
				if (field.ofWater(koord))
				{
					fitnes[i]=max;
					break;
				}
			}
			if (fitnes[i]==-1)
				fitnes[i]=0;
			else if (fitnes[i]!=max)
				fitnes[i]=field.distance(koord);
		}		
	}
	public void sort()
	{
		int bufArray[]=new int[size];
		int bufVar=0;
		for (int i=0;i<count;i++)		//bubble sort
			for(int j=1;j<count;j++)
				if(fitnes[j]<fitnes[j-1])
				{
					bufVar=fitnes[j-1];
					fitnes[j-1]=fitnes[j];
					fitnes[j]=bufVar;
					
					bufArray=this.chromosoms[j-1];
					this.chromosoms[j-1]=this.chromosoms[j];
					this.chromosoms[j]=bufArray;
				}
	}
	public void newGeneration()
	{
		int parentsConst=2;	 //The number of parents with one child
		Random random = new Random();
		int parentsBroad=(int)(this.count/parentsConst);	//The number of chromosomes giving children
		int children[][]=new int[this.count][this.size];	//The population of children
		int parents[][]=new int[parentsConst][this.size];	//The parents (with one child)
		for(int i=0;i<count;i++)
		{
			for(int k=0;k<parentsConst;k++)			//The choice of parents
				parents[k]=this.chromosoms[random.nextInt(parentsBroad)];
			for(int j=0;j<size;j++)
			{
					int parentsNumber=random.nextInt(parentsConst); //A parent sending a child sign
					children[i][j]=parents[parentsNumber][j];
			}
			if(random.nextDouble()<=mutation)
			{
				int j=random.nextInt(size);
				children[i][j]=random.nextInt(4);
			}
		}
		this.setChromosoms(children);	//The old population is dead. Children are now new population.			
	}
	/*
	 * 
	 */
	public boolean stopMarker()
	{
		for (int i=0; i<count; i++)
		{
			if (fitnes[i]==0)
				return true;
		}
		return false;
	}
	public void fitnesPrint()
	{
		for(int i=0;i<count;i++)
			System.out.print(fitnes[i]+" ");
		System.out.println();
	}
	public int[] returnSmartDog()
	{
		for(int i=0;i<count;i++)
			if(fitnes[i]==0)
				return chromosoms[i];
		return null;
	}
}
